package com.bjpowernode.security04mysql.config;


import com.bjpowernode.security04mysql.filter.CaptchaCodeFilter;
import com.bjpowernode.security04mysql.handler.AppAccessDeniedHandler;
import com.bjpowernode.security04mysql.handler.AppAuthenticationFailureHandler;
import com.bjpowernode.security04mysql.handler.AppAuthenticationSuccessHandler;
import com.bjpowernode.security04mysql.handler.AppLogoutSuccessHandler;
import com.bjpowernode.security04mysql.service.impl.AppUserServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * security配置类
 */
@Configuration
@EnableMethodSecurity(prePostEnabled = true) //开启security授权
public class MySecurityConfiguration {

    @Resource
    private AppAccessDeniedHandler appAccessDeniedHandler;

    @Resource
    private AppAuthenticationFailureHandler appAuthenticationFailureHandler;

    @Resource
    private AppAuthenticationSuccessHandler appAuthenticationSuccessHandler;

    @Resource
    private AppLogoutSuccessHandler appLogoutSuccessHandler;

    @Resource
    private AppUserServiceImpl appUserServiceImpl;


    @Resource
    private CaptchaCodeFilter captchaCodeFilter;

    /**
     * 编写security的配置
     * @param httpSecurity
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {

        //让验证码的过滤器在用户名和密码过滤器之前运行
        httpSecurity.addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class);

        //-----------新增 配置我们自己的AppUserServiceImpl
        httpSecurity.userDetailsService(appUserServiceImpl);


        //配置没有权限的handler
        httpSecurity.exceptionHandling(handler -> handler.accessDeniedHandler(appAccessDeniedHandler));

       //配置认证成功和失败的handler
        httpSecurity.formLogin(handler -> handler
                .usernameParameter("uname")//----新增 默认获取的是username
                .passwordParameter("pwd") //----新增 默认获取的是password
                .loginPage("/toLogin")  //----新增 跳转到登录页面的Controller地址
                .loginProcessingUrl("/login/doLogin")//----新增 处理请求的地址
                .successHandler(appAuthenticationSuccessHandler)
                .failureHandler(appAuthenticationFailureHandler));

        //放行登录等请求  不需要security验证token的地址写到这里
        //除了/toLogin /login/doLogin 之外的其他请求，都需要security验证token
        httpSecurity.authorizeHttpRequests(request ->
                request.requestMatchers("/toLogin", "/login/doLogin","/code/image")
                        .permitAll()
                        .anyRequest().authenticated());

        //关闭csrf
        httpSecurity.csrf(csrf -> csrf.disable());
        //允许前端跨域访问
        //httpSecurity.cors(cors -> cors.disable());


        //配置退出的handler
        httpSecurity.logout(handler -> handler.logoutSuccessHandler(appLogoutSuccessHandler));


        //跨域配置
        httpSecurity.cors(cors -> { //允许前端跨域访问
            cors.configurationSource(configurationSource());
        });

        return httpSecurity.build();
    }


    /**
     * 配置加密器
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Bean //配置跨域
    public CorsConfigurationSource configurationSource() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();

        //跨域配置
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*")); //允许任何来源，http://localhost:10492/
        corsConfiguration.setAllowedMethods(Arrays.asList("*")); //允许任何请求方法，post、get、put、delete
        corsConfiguration.setAllowedHeaders(Arrays.asList("*")); //允许任何的请求头 (jwt)

        //注册跨域配置
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); //  /api/user,  /api/user/12082
        return urlBasedCorsConfigurationSource;
    }

}
